package futbol.tacticas.concursantes2007.SeteTeam.jugadores.geometria;

import java.awt.Point;

/**
 * Recopilacion de calculos a realizar sobre una o varias rectas
 * 
 * @author llua
 *
 */
public final class Linea {
	private final double m; //Pendiente
	private final double n; //Ordenada al origen
	
	/**
	 * Genera una linea a partir de una Pendiente y su Ordenada al origen
	 * @param m Pendiente
	 * @param n Ordenada al origen
	 */
	public Linea(final double m, final double n) {
		this.m = m;
		this.n = n;
	}
	
	/**
	 * Genera una linea a partir de 2 puntos
	 * @param a
	 * @param b
	 */
	public Linea(Point a, Point b){
		if(a.equals(b)){
			m=0;
			n=0;
		}else{
			m=((b.getY()-a.getY())/(b.getX()-a.getX()));
			n=((a.getY() * b.getX())-(b.getY() * a.getX()))/(b.getX()-a.getX());
		}
	}
	
	public static Linea buildLinea(Point a, Point b){
		if(a.equals(b))
			return null;
			
		return new Linea(a, b);
	}
	
	/**
	 * Retorna la pendiente
	 * @return m
	 */
	public double getM() {
		return m;
	}

	/**
	 * Retorna la ordenada en el origen
	 * @return
	 */
	public double getN() {
		return n;
	}
	
	public static double calcularDistancia(final Linea linea, final Point punto) throws ArithmeticException{
		Point proyeccion = linea.calcularProyeccionPerpendicular(punto);
		if(proyeccion==null){
			return Double.POSITIVE_INFINITY;
		}
		return punto.distance(proyeccion);
	}
	
	public double calcularDistancia(final Point punto) throws ArithmeticException{
		return calcularDistancia(this,punto);
	}
	
	public static Point calcularInterseccion(final Linea linea1, final Linea linea2) throws ArithmeticException{
		if(linea1 ==null || linea2 ==null || (linea1.m-linea2.m)==0.0)
			return null;
		
		final double x = (linea2.n-linea1.n)/(linea1.m-linea2.m);
		final double y = ((linea1.m * linea2.n)-(linea2.m * linea1.n))/(linea1.m-linea2.m);
		return new Point((int)x,(int)y);
	}
	
	public Point calcularInterseccion(final Linea linea) throws ArithmeticException{
		return calcularInterseccion(this,linea);
	}
	
	public static Linea calcularPerpendicular(Linea linea, Point punto) throws ArithmeticException{
		if(linea==null || punto == null || linea.m==0.0){
			return null;
		}
			
		final double m = -1/linea.m;
		final double n = punto.getY()-(punto.getX() * m);
		return new Linea(m,n);
	}
	
	public Linea calcularPerpendicular(Point punto) throws ArithmeticException{
		return calcularPerpendicular(this, punto);
	}
	
	public static Point calcularProyeccionPerpendicular(Linea linea, Point punto) throws ArithmeticException{
		return linea.calcularInterseccion(linea.calcularPerpendicular(punto));
	}
	
	public Point calcularProyeccionPerpendicular(Point punto) throws ArithmeticException{
		return calcularProyeccionPerpendicular(this, punto);
	}
	
	public Point calcularX(final double y) throws ArithmeticException{
		return new Point((int)((y-n)/m),(int)y);
	}
	
	public Point calcularY(final double x) throws ArithmeticException{
		return new Point((int)x,(int)((m*x)+n));
	}
	
	public String toString(){
		return "Pendiente: "+m+" corte Y: "+n;
	}
}
